<template>
	<SlotModal ref='slotModalRef' v-bind='slotModalConfig'>
		<n-form ref='formRef' v-bind='formConfig'
				:model='formData' :rules='formRules'>
			<n-grid :x-gap='24' :cols='2'>
				<n-form-item-grid-item span='1' label='上级菜单编码' path='parentMenuCode'>
					<n-input v-model:value='formData.parentMenuCode'
							 style='width:100%' disabled clearable/>
				</n-form-item-grid-item>
				<n-form-item-grid-item span='1' label='菜单序号' path='sort'>
					<n-input-number v-model:value='formData.sort as number'
									style='width:100%' min='0' clearable/>
				</n-form-item-grid-item>
				<n-form-item-grid-item span='2' label='菜单类型' path='menuType'>
					<n-select v-model:value='formData.menuType'
							  :options='optionList.menuType.list'
							  :placeholder='optionList.menuType.placeholder'
							  :loading='optionList.menuType.loading'
							  :disabled='optionList.menuType.disabled'
							  virtual-scroll filterable clearable/>
				</n-form-item-grid-item>
				<n-form-item-grid-item span='1' label='菜单编码' path='menuCode'>
					<n-tooltip placement='bottom' trigger='click'>
						<template v-slot:trigger>
							<n-input v-model:value='formData.menuCode' placeholder='请输入菜单编码'
									 clearable/>
						</template>
						菜单编码由一个大写英文字母+3位数字组成,如A001
						<br>
						如有多层级则往后追加,如A001B002C110
					</n-tooltip>
				</n-form-item-grid-item>
				<n-form-item-grid-item span='1' label='菜单名称' path='menuName'>
					<n-input v-model:value='formData.menuName' placeholder='请输入菜单名称'
							 clearable/>
				</n-form-item-grid-item>
				<!--只有操作权限可以填写权限字符串-->
				<n-form-item-grid-item v-if='"OPERATE"===formData.menuType'
									   span='2' label='权限字符串' path='menuPermission'>
					<n-input v-model:value='formData.menuPermission' placeholder='请输入权限字符串'
							 clearable/>
				</n-form-item-grid-item>
				<!--只有菜单可以填写菜单路径-->
				<n-form-item-grid-item v-if='"MENU"===formData.menuType'
									   span='2' label='菜单路径' path='menuPath'>
					<n-input v-model:value='formData.menuPath' placeholder='请输入菜单路径'
							 clearable/>
				</n-form-item-grid-item>
				<!--只有目录和菜单可以填写-->
				<n-form-item-grid-item v-if='(["DIR","MENU"]).includes(formData.menuType as string)'
									   span='1' label='菜单图标类型' path='menuIconType'>
					<n-select v-model:value='formData.menuIconType'
							  :options='optionList.iconType.list'
							  :placeholder='optionList.iconType.placeholder'
							  :loading='optionList.iconType.loading'
							  :disabled='optionList.iconType.disabled'
							  :render-label='renderIconTypeLabel'
							  :onUpdate:value='onMenuIconTypeChange'
							  virtual-scroll filterable clearable/>
				</n-form-item-grid-item>
				<!--只有目录和菜单可以填写-->
				<n-form-item-grid-item v-if='(["DIR","MENU"]).includes(formData.menuType as string)'
									   span='1' label='菜单图标' path='menuIcon'>
					<n-select v-model:value='formData.menuIcon'
							  :options='optionList.menuIcon.list'
							  :placeholder='optionList.menuIcon.placeholder'
							  :loading='optionList.menuIcon.loading'
							  :disabled='!formData.menuIconType'
							  :render-label='renderMenuIconLabel'
							  virtual-scroll filterable clearable/>
				</n-form-item-grid-item>
				<n-form-item-grid-item v-if='"MENU"===formData.menuType'
									   span='1' label='标签图标类型' path='tabIconType'>
					<n-select v-model:value='formData.tabIconType'
							  :options='optionList.iconType.list'
							  :placeholder='optionList.iconType.placeholder'
							  :loading='optionList.iconType.loading'
							  :disabled='optionList.iconType.disabled'
							  :render-label='renderIconTypeLabel'
							  :onUpdate:value='onTabIconTypeChange'
							  virtual-scroll filterable clearable/>
				</n-form-item-grid-item>
				<n-form-item-grid-item v-if='"MENU"===formData.menuType'
									   span='1' label='标签图标' path='tabIcon'>
					<n-select v-model:value='formData.tabIcon'
							  :options='optionList.tabIcon.list'
							  :placeholder='optionList.tabIcon.placeholder'
							  :loading='optionList.tabIcon.loading'
							  :disabled='!formData.tabIconType'
							  :render-label='renderTabIconLabel'
							  virtual-scroll filterable clearable/>
				</n-form-item-grid-item>
				<n-form-item-grid-item v-if='"MENU"===formData.menuType'
									   span='1' label='是否保活' path='isCache'>
					<n-switch v-model:value='formData.isCache' size='large'
							  :checkedValue='true'
							  :uncheckedValue='false'>
						<template v-slot:checked>保活</template>
						<template v-slot:unchecked>销毁</template>
					</n-switch>
				</n-form-item-grid-item>
				<n-form-item-grid-item span='1' label='是否启用' path='status'>
					<n-switch v-model:value='formData.status' size='large'
							  :checkedValue='true' :uncheckedValue='false'>
						<template v-slot:checked>启用</template>
						<template v-slot:unchecked>禁用</template>
					</n-switch>
				</n-form-item-grid-item>
				<n-grid-item span='2' :show-feedback='false'>
					<n-flex justify='center' align='center'
							:wrap='false' inline style='width:100%;'>
						<n-button round secondary type='info'
								  @click='submitEvent'>
							提交
						</n-button>
						<n-button round secondary type='default'
								  @click='clearFormData'>
							重置
						</n-button>
					</n-flex>
				</n-grid-item>
			</n-grid>
		</n-form>
	</SlotModal>
</template>
<script lang='ts' setup>
import { defineAsyncComponent, h, onBeforeMount, onMounted, PropType, reactive, ref, VNodeChild } from 'vue';
// axios
import axios from '@/config/axios/index.ts';
// 模态框和打印组件
import { VxeUI } from '@/config/vxe/index.ts';
import { getAllSvgIconList } from '@/config/icon/SvgIcons.ts';
import { getAllClassIconList } from '@/config/icon/ClassIcons.ts';
import type { JsonResultProps } from '#/JsonResult.d.ts';
import { FormInst, FormProps, FormRules, FormValidationError, SelectOption } from 'naive-ui';
import type { MenuProps } from '#/src/components/page/systemManager/menuMaintain/MenuMaintainProps.d.ts';
import type { Options } from '#/Options.d.ts';
import type { Dict, DictionaryOption } from '#/Dictionary.d.ts';
import { clone } from 'xe-utils';
// ----------------------------------------------------------------------
const SlotModal = defineAsyncComponent(() => import('@/components/customComponents/modal/SlotModal.vue'));
const SvgIcon = defineAsyncComponent(() => import('@/components/customComponents/icon/SvgIcon.vue'));
const ClassIcon = defineAsyncComponent(() => import('@/components/customComponents/icon/ClassIcon.vue'));
// ----------------------------------------------------------------------
const props = defineProps({
	reLoad : {
		type    : Function,
		require : true,
		default : null
	},
	dict   : {
		type    : Object as PropType<Dict>,
		require : true,
		default : () => {}
	}
});
// ----------------------------------------------------------------------
const slotModalConfig = reactive({
	reLoad            : () => props.reLoad(),
	onMountedEvent    : null,
	onCloseModalEvent : () => clearFormData(),
	onZoomModalEvent  : () => onZoomModalEvent(),
	resetEvent        : () => resetEvent()
});
const formConfig = reactive<FormProps>({
	labelWidth           : 120,
	labelAlign           : 'left',
	labelPlacement       : 'left',
	size                 : 'large',
	requireMarkPlacement : 'right-hanging'
});
// ----------------------------------------------------------------------
const slotModalRef = ref<InstanceType<typeof SlotModal>>();
const formRef = ref<FormInst>();
// ----------------------------------------------------------------------
const formData = reactive<Partial<MenuProps>>({});
const formRules = reactive<FormRules>({
	sort           : {
		required : true,
		type     : 'number',
		trigger  : ['input', 'blur'],
		message  : '菜单序号是必须的'
	},
	menuCode       : {
		required : true,
		type     : 'string',
		trigger  : ['input', 'blur'],
		message  : '菜单编码是必须的'
	},
	menuName       : {
		required : true,
		type     : 'string',
		trigger  : ['input', 'blur'],
		message  : '菜单名称是必须的'
	},
	menuType       : {
		required : true,
		type     : 'string',
		trigger  : ['input', 'blur'],
		message  : '菜单类型是必选的'
	},
	menuPermission : {
		required : true,
		type     : 'string',
		trigger  : ['input', 'blur'],
		message  : '权限字符串是必输的'
	},
	menuPath       : {
		required : true,
		type     : 'string',
		trigger  : ['input', 'blur'],
		message  : '菜单路径是必选的'
	},
	menuIcon       : {
		required : true,
		type     : 'string',
		trigger  : ['input', 'blur'],
		message  : '菜单图标是必须的'
	},
	menuIconType   : {
		required : true,
		type     : 'string',
		trigger  : ['input', 'blur'],
		message  : '菜单图标类型是必选的'
	},
	tabIcon        : {
		required : true,
		type     : 'string',
		trigger  : ['input', 'blur'],
		message  : '标签图标是必须的'
	},
	tabIconType    : {
		required : true,
		type     : 'string',
		trigger  : ['input', 'blur'],
		message  : '标签图标类型是必选的'
	},
	isCache        : {
		required : true,
		type     : 'boolean',
		trigger  : ['change'],
		message  : '是否保活是必选的'
	},
	status         : {
		required : true,
		type     : 'boolean',
		trigger  : ['change'],
		message  : '是否启用是必须的'
	}
});
// ----------------------------------------------------------------------
// 接口下拉选
const optionList = reactive<Options>({
	menuType : {
		loading     : false,
		disabled    : false,
		placeholder : '请选择菜单类型',
		list        : []
	},
	iconType : {
		loading     : false,
		disabled    : false,
		placeholder : '请选择图标类型',
		list        : []
	},
	// 菜单
	menuIcon : {
		loading     : false,
		disabled    : false,
		placeholder : '请选择菜单图标',
		list        : []
	},
	// 标签
	tabIcon  : {
		loading     : false,
		disabled    : false,
		placeholder : '请选择标签图标',
		list        : []
	},
	menuPath : {
		loading     : false,
		disabled    : false,
		placeholder : '请选择菜单路径',
		list        : []
	}
});
// ----------------------------------------------------------------------
const allIconList = reactive({
	svg   : null as Array<DictionaryOption> | null,
	class : null as Omit<Array<DictionaryOption>, 'value'> | null
});
// ----------------------------------------------------------------------
onBeforeMount(async () => {
	optionList.menuIcon.loading = true;
	optionList.tabIcon.loading = true;
	allIconList.svg = getAllSvgIconList();
	allIconList.class = getAllClassIconList();
	optionList.menuIcon.loading = false;
	optionList.tabIcon.loading = false;
});
onMounted(async () => {
});
const initDict = async (): Promise<void> => {
	// -------------------------------------
	optionList.menuIcon.disabled = true;
	optionList.tabIcon.disabled = true;
	// -------------------------------------
	optionList.menuType.loading = true;
	optionList.menuType.disabled = true;
	optionList.iconType.loading = true;
	optionList.iconType.disabled = true;
	/*menuType*/
	optionList.menuType.list = props.dict.menuType;
	optionList.menuType.loading = false;
	optionList.menuType.disabled = false;
	/*iconType*/
	optionList.iconType.list = props.dict.iconType;
	optionList.iconType.loading = false;
	optionList.iconType.disabled = false;
};
const showModal = async (rowData: MenuProps) => {
	await slotModalRef.value!.openModal({
		height     : '500',
		width      : '700',
		title      : '新增子项菜单',
		showClose  : true,
		showZoom   : true,
		fullscreen : false
	});
	formData.parentMenuCode = rowData.menuCode;
	await initDict();
};
const onZoomModalEvent = async () => {
};
const clearFormData = async () => {
	// 清理表单数据
	Object.assign(formData, {
		sort           : null,
		menuCode       : null,
		menuName       : null,
		menuType       : null,
		menuPermission : null,
		menuPath       : null,
		menuIconType   : null,
		menuIcon       : null,
		tabIconType    : null,
		tabIcon        : null,
		isCache        : true,
		status         : true
	});
	// 去除表单校验提示
	formRef.value?.restoreValidation();
};
const resetEvent = async () => {
	// 清理表单数据
	Object.assign(formData, {
		sort           : null,
		parentMenuCode : null,
		menuCode       : null,
		menuName       : null,
		menuType       : null,
		menuPermission : null,
		menuPath       : null,
		menuIconType   : null,
		menuIcon       : null,
		tabIconType    : null,
		tabIcon        : null,
		isCache        : true,
		status         : true
	});
	// 去除表单校验提示
	formRef.value?.restoreValidation();
};
const submitEvent = async () => {
	// 校验菜单
	formRef.value?.validate((errors?: Array<FormValidationError>): void => {
		if (errors) {
			VxeUI.modal.message({ content : '请先完善填写的内容!', status : 'warning', id : 'validateMessage' });
		} else {
			// 判断是否保活的默认值,菜单让用户自己选
			// 如果是接口权限和目录,那么只能设置false
			switch (formData.menuType) {
				case 'DIR':
					formData.isCache = false;
					break;
				case 'OPERATE':
					formData.isCache = false;
					break;
			}
			// 提交数据
			axios<any, JsonResultProps<any>, any>({
				method : 'POST',
				url    : '/menu/add',
				data   : formData
			}).then((jsonResult: JsonResultProps<any>) => {
				if (jsonResult['status']) {
					// 提示用户
					VxeUI.modal.message({
						content : jsonResult['msg'],
						status  : 'success',
						id      : 'successMessage'
					});
					// 刷新数据
					props.reLoad();
					slotModalRef.value!.closeModal();
				} else {
					VxeUI.modal.message({
						content : jsonResult['msg'],
						status  : 'warning',
						id      : 'failedMessage'
					});
				}
			}).catch((error: unknown) => {
				console.error(error);
				VxeUI.modal.message({
					content : '系统异常,请稍后再试',
					status  : 'error',
					id      : 'errorMessage'
				});
			});
		}
	});
};
// -----------------------------------------------------------------------------------
const onMenuIconTypeChange = () => {
	formData.menuIcon = null;
	let iconList: any;
	switch (formData.menuIconType) {
		case 'class':
			iconList = allIconList.class;
			break;
		case 'svg':
			iconList = allIconList.svg;
			break;
	}
	// -------------------------------------
	optionList.menuIcon.list = clone(iconList, true);
	optionList.menuIcon.loading = false;
	optionList.menuIcon.disabled = false;
};
const renderMenuIconLabel = (option: SelectOption): VNodeChild => {
	if (option?.type) {
		if ('group' === option.type) {
			// @ts-ignore
			return option.label;
		}
	}
	if ('class' === formData.menuIconType) {
		return [
			// @ts-ignore
			h(ClassIcon, { 'icon-class' : option.value }),
			'  ',
			` ${option.label}`
		];
	}
	if ('svg' === formData.menuIconType) {
		return [
			// @ts-ignore
			h(SvgIcon, {
				'icon-type'  : option.key,
				'icon-class' : option.value
			}),
			'  ',
			` ${option.label}`
		];
	}
};
// -----------------------------------------------------------------------------------
const onTabIconTypeChange = () => {
	formData.tabIcon = null;
	let iconList: any;
	switch (formData.tabIconType) {
		case 'class':
			iconList = allIconList.class;
			break;
		case 'svg':
			iconList = allIconList.svg;
			break;
	}
	// -------------------------------------
	optionList.tabIcon.list = clone(iconList, true);
	optionList.tabIcon.loading = false;
	optionList.tabIcon.disabled = false;
};
const renderTabIconLabel = (option: SelectOption): VNodeChild => {
	if (option?.type) {
		if ('group' === option.type) {
			// @ts-ignore
			return option.label;
		}
	}
	if ('class' === formData.tabIconType) {
		return [
			// @ts-ignore
			h(ClassIcon, { 'icon-class' : option.value }),
			'  ',
			` ${option.label}`
		];
	}
	if ('svg' === formData.tabIconType) {
		return [
			// @ts-ignore
			h(SvgIcon, {
				'icon-type'  : option.key,
				'icon-class' : option.value
			}),
			'  ',
			` ${option.label}`
		];
	}
};
// -----------------------------------------------------------------------------------
const renderIconTypeLabel = (option: SelectOption): VNodeChild => {
	if ('class' === option.value) {
		return [
			// @ts-ignore
			h(SvgIcon, {
				'icon-type'  : 'customized',
				'icon-class' : 'fileExtension/font/customized-font'
			}),
			'  ',
			` ${option.label}`
		];
	}
	if ('svg' === option.value) {
		return [
			// @ts-ignore
			h(SvgIcon, {
				'icon-type'  : 'customized',
				'icon-class' : 'fileExtension/svg/customized-svg'
			}),
			'  ',
			` ${option.label}`
		];
	}
};
// 导出方法
defineExpose({ showModal });
</script>